#include "dlist.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// 定义命令项结构体 - 与实际系统中的log_item_t结构体类似
typedef void (*cmd_handler_t)(char *param);
typedef struct {
    const char *cmd_name;      // 命令名称
    cmd_handler_t handler;     // 命令处理函数
    struct list_head list;     // 链表节点
} command_item_t;

// 注意：在实际的嵌入式系统中，命令处理通常在一个单独的任务(线程)中运行
// 这样可以不阻塞主程序的执行，并能实时响应命令输入
// 这里我们使用简化的实现，但保留了核心的命令处理逻辑

// 命令表的哈希表大小
#define CMD_HASH_SIZE 32

// 命令哈希表
struct list_head cmd_hash[CMD_HASH_SIZE];

// 哈希函数
unsigned int cmd_hash_func(const char *str)
{
    unsigned int hash = 0;
    while (*str) {
        hash = (hash * 31) + *str++;
    }
    return hash % CMD_HASH_SIZE;
}

// 添加命令到哈希表
void add_command(command_item_t *item)
{
    unsigned int index = cmd_hash_func(item->cmd_name);
    list_add(&item->list, &cmd_hash[index]);
}

// 查找命令
cmd_handler_t find_command(const char *cmd_name)
{
    unsigned int index = cmd_hash_func(cmd_name);
    struct list_head *pos;
    command_item_t *item;
    
    list_for_each(pos, &cmd_hash[index]) {
        item = list_entry(pos, command_item_t, list);
        if (strcmp(item->cmd_name, cmd_name) == 0) {
            return item->handler;
        }
    }
    return NULL;
}

// 解析命令参数
void parse_command(char *cmd, char **cmd_name, char **param)
{
    *cmd_name = strtok(cmd, " ");
    *param = strtok(NULL, "\0");
}

/* 执行命令
 * 这个函数类似于实际系统中的log_handler函数
 * 
 * 在实际系统中：
 * - log_handler函数接收完整的命令字符串
 * - 它解析命令和参数(使用=strtok或strsep分隔)
 * - 然后调用log_action查找对应的处理函数
 * - 最后执行找到的处理函数
 * 
 * 我们这里的实现更加简化，但保留了核心的命令查找和执行逻辑
 */
int execute_command(char *cmd)
{
    char *cmd_name, *param;
    cmd_handler_t handler;
    
    parse_command(cmd, &cmd_name, &param);
    
    if (!cmd_name) {
        return -1;
    }
    
    handler = find_command(cmd_name);
    if (handler) {
        handler(param);
        return 0;
    }
    
    return -1;
}

// 显示所有可用命令
void show_commands(void)
{
    int i;
    struct list_head *pos;
    command_item_t *item;
    
    printf("\n可用命令列表：\n");
    for (i = 0; i < CMD_HASH_SIZE; i++) {
        if (!list_empty(&cmd_hash[i])) {
            list_for_each(pos, &cmd_hash[i]) {
                item = list_entry(pos, command_item_t, list);
                printf("  %s\n", item->cmd_name);
            }
        }
    }
    printf("\n");
}

// 命令处理函数示例
void cmd_help(char *param)
{
    show_commands();
    printf("输入命令格式：命令名 [参数]\n");
    printf("例如：help, version, echo hello\n");
}

void cmd_version(char *param)
{
    printf("命令处理器版本 1.0\n");
    printf("基于dlist双向链表库实现\n");
}

void cmd_echo(char *param)
{
    if (param) {
        printf("%s\n", param);
    } else {
        printf("请输入要回显的内容\n");
    }
}

void cmd_exit(char *param)
{
    printf("感谢使用命令处理器！\n");
    exit(0);
}

// 定义命令列表
command_item_t command_list[] = {
    {"help", cmd_help, {NULL, NULL}},
    {"version", cmd_version, {NULL, NULL}},
    {"echo", cmd_echo, {NULL, NULL}},
    {"exit", cmd_exit, {NULL, NULL}}
};

int main()
{
    int i;
    char cmd_buf[256];
    
    // 初始化命令哈希表
    for (i = 0; i < CMD_HASH_SIZE; i++) {
        INIT_LIST_HEAD(&cmd_hash[i]);
    }
    
    // 添加所有命令到哈希表
    for (i = 0; i < sizeof(command_list) / sizeof(command_item_t); i++) {
        INIT_LIST_HEAD(&command_list[i].list);
        add_command(&command_list[i]);
    }
    
    printf("===== 命令处理器演示程序 =====\n");
    printf("基于dlist双向链表库实现的命令解析系统\n");
    printf("输入 'help' 查看可用命令\n\n");
    
    /* 命令循环
     * 在实际的嵌入式系统中(如您看到的log_service.c)，命令处理通常在单独的任务中运行
     * 例如：
     * - log_service函数是一个任务函数，包含while(1)循环
     * - 它会调用log_get_buffer()获取输入的命令(可能来自UART等)
     * - 然后通过log_handler()处理命令
     * - 处理完成后释放信号量并等待下一个命令
     * 
     * 我们这里使用简化的while(1)循环是为了模拟这个过程，在实际应用中：
     * 1. 您可能需要创建一个单独的任务/线程运行命令处理器
     * 2. 使用信号量或队列来实现命令的安全传递
     * 3. 添加适当的锁机制来保护共享资源
     * 4. 实现更复杂的命令解析和参数处理逻辑
     */
    while (1) {
        printf("# ");
        if (fgets(cmd_buf, sizeof(cmd_buf), stdin) == NULL) {
            continue;
        }
        
        // 移除换行符
        char *newline = strchr(cmd_buf, '\n');
        if (newline) {
            *newline = '\0';
        }
        
        // 执行命令
        if (execute_command(cmd_buf) != 0) {
            printf("未知命令：%s\n", cmd_buf);
            printf("输入 'help' 查看可用命令\n");
        }
    }
    
    return 0;
}